/*
 * Copyright 2020-2025 the original author or authors.
 * You cannot use this file unless authorized by the author.
 */
package org.ipig.data.rdbms.mapper;


import org.ipig.commons.helper.DateTimeHelper;
import org.ipig.constants.FieldCnst;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.jdbc.core.RowMapper;

import javax.persistence.Column;
import javax.persistence.Entity;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Row Mapper Service
 *
 * @author <a href="mailto:comchnts@163.com">chinats</a>
 * @version $$Id: RowMapperService.java 3 2020-01-21 09:36:33Z ts <comchnts@163.com> $$
 * @since 1.0
 */
public interface RowMapperService<T> extends RowMapper<T> {
    /**
     * getEntityClass
     *
     * @return
     */
    public Class<T> getEntityClass();

    /**
     * parseDateAble
     *
     * @return
     */
    public default Boolean parseDateAble() {
        return true;
    }

    @Override
    public default T mapRow(ResultSet rs, int rowNum) throws SQLException {
        return mapEntity(rs);
    }

    /**
     * 将java.sql.ResultSet映射成给定的泛型类型实例
     *
     * @param rs java.sql.ResultSet
     * @return 泛型T类型实例
     */
    public default T mapEntity(ResultSet rs) {
        try {
            if (rs != null) {
                Class<T> outputClass = getEntityClass();
                if (outputClass.isAnnotationPresent(Entity.class)) {
                    List<Field> fieldList = new ArrayList<Field>();
                    Class tempClass = outputClass;
                    while (tempClass != null) {
                        fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
                        tempClass = tempClass.getSuperclass();
                    }
//                    Field[] fields = outputClass.getFields();
                    T bean = outputClass.newInstance();
                    for (Field field : fieldList) {
                        if (field.isAnnotationPresent(Column.class)) {
                            Column column = field.getAnnotation(Column.class);
                            String name = column.name();
                            try {
                                if (StringUtils.isBlank(name)) {
                                    name = field.getName();
                                }
                                Object object = rs.getObject(name);
                                if (parseDateAble()
                                        && (object instanceof Date || object instanceof oracle.sql.TIMESTAMP)) {
                                    if (object instanceof oracle.sql.TIMESTAMP) {
                                        object = oracle.sql.TIMESTAMP.class.cast(object).dateValue();
                                    }
                                    object = DateTimeHelper.yyyyMMddHHmmss(Date.class.cast(object));
                                }
                                if (object != null) {
                                    BeanUtils.setProperty(bean, field.getName(), object);
                                }
                            } catch (SQLException ex) {
                                if (StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.ID)
                                        || StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.DELETED_FLAG)
                                        || StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.MODIFY_TIME)
                                        || StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.CREATE_TIME)
                                        || StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.CREATOR_ID)
                                        || StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.VERSION)
                                        || StringUtils.equalsIgnoreCase(field.getName(), FieldCnst.MODIFIER_ID)) {
                                    // 技术规范下的公用字段处理
//                                    System.out.println(MessageFormat.format("类: {0} 字段属性：{1}，DB列名: {2}, 提示信息 {3}", outputClass.getName(), field.getName(), name, ex.getMessage()));
                                } else {
                                    System.err.println(MessageFormat.format("类: {0} 字段属性：{1}，DB列名: {2}, 错误信息 {3}", outputClass.getName(), field.getName(),
                                            name, ex.getMessage()));
                                }
                            } catch (Exception ex) {
                                System.err.println(MessageFormat.format("类: {0} 字段属性：{1}，DB列名: {2}, 错误信息 {3}", outputClass.getName(), field.getName(),
                                        name, ex.getMessage()));
                            }
                        }
                    }
                    if (bean != null) {
                        handleSpecialFields(bean);
                    }
                    return bean;
                }
            } else {
                return null;
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 用于特殊字段的处理
     *
     * @param t
     */
    public void handleSpecialFields(T t);
}
